package utils

import java.io.{ByteArrayOutputStream, File, FileInputStream, FileOutputStream, OutputStreamWriter}
import java.nio.file.Files
import java.text.SimpleDateFormat
import java.util.zip.GZIPOutputStream

import javax.imageio.ImageIO
import org.apache.commons.io.{FileUtils, IOUtils}
import org.apache.commons.lang3.StringUtils
import org.joda.time.DateTime
import play.api.libs.json.{JsObject, Json}
import play.api.mvc.Result
//import org.apache.commons.math3.stat.StatUtils
//import org.apache.commons.math3.stat.descriptive.moment.StandardDeviation
//import org.saddle.io._
//import CsvImplicits._
//import javax.imageio.ImageIO
//import org.apache.pdfbox.pdmodel.PDDocument
//import org.apache.pdfbox.rendering.PDFRenderer

import scala.collection.JavaConverters._
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.math.log10
import implicits.Implicits._


object Utils {

  def isWindows = {
    System.getProperty("os.name") match {
      case x if x.contains("Windows") => true
      case _ => false
    }
  }

  val Rscript = {
    "Rscript"
  }

  def deleteDirectory(direcotry: File) = {
    try {
      FileUtils.deleteDirectory(direcotry)
    } catch {
      case _ =>
    }
  }

  def getTime(startTime: Long) = {
    val endTime = System.currentTimeMillis()
    (endTime - startTime) / 1000.0
  }

  def logTime(startTime: Long) = {
    val time = getTime(startTime)
    println(time)
  }

  def logTime(beforeStr:String,startTime: Long) = {
    val time = getTime(startTime)
    println(beforeStr,time)
  }

  def spentTime(f: () => Unit) = {
    val startTime = System.currentTimeMillis()
    f()
    val time = getTime(startTime)
    println(time)
  }

  def execFuture[T](f: Future[T]): T = {
    Await.result(f, Duration.Inf)
  }

  def getValue[T](kind: T, noneMessage: String = ""): String = {
    kind match {
      case x if x.isInstanceOf[DateTime] => val time = x.asInstanceOf[DateTime]
        time.toString("yyyy-MM-dd HH:mm:ss")
      case x if x.isInstanceOf[Option[T]] => val option = x.asInstanceOf[Option[T]]
        if (option.isDefined) getValue(option.get, noneMessage) else noneMessage
      case x if x.isInstanceOf[Seq[T]] => val list = x.asInstanceOf[Seq[T]]
        list.mkString(";")
      case _ => kind.toString
    }
  }

  def mean(x: List[Double]) = {
    x.sum / x.size
  }

  def result2Future(rs: Result) = {
    Future.successful(rs)
  }

  def getRelativePath(parent: File, file: File) = {
    val parentPath = parent.getAbsolutePath.slashL2R
    file.getAbsolutePath.slashL2R.replaceAll(s"^${parentPath}/", "")
  }

  def gZip(file: File, gzFile: File) = {
    val fin = new FileInputStream(file)
    val fout = new FileOutputStream(gzFile)
    val gzout = new GZIPOutputStream(fout)

    def loop: Unit = {
      val buf = new Array[Byte](1024)
      val num = fin.read(buf)
      num match {
        case x if x == -1 =>
        case _ =>
          gzout.write(buf, 0, num)
          loop
      }
    }

    loop
    gzout.close()
    fout.close()
    fin.close()
  }

  def isLike(v: String, dbV: String) = {
    if (v.isEmpty) true else dbV.contains(v)
  }

}
